#include "Input.h"

DInput::DInput()
	: m_pDIObject(NULL)
	, m_pDIKeyboard(NULL)
	, m_pDIMouse(NULL)
	, m_bInitialized(false)
	, m_isCaps(true)
{
	for(int i = 0; i < 4; i++)
		m_bMouseButtonDown[i] = false;

	for(int i = 0; i < 256; i++)
		m_kbWasHit[i] = false;
}

// initialize object and peripheral devices
bool DInput::Init(HWND hWnd, HINSTANCE hInst)
{
	m_hWnd = hWnd;
	// create the direct input object
	DirectInput8Create(hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&m_pDIObject, NULL);

	// use that object to create the keyboard and mouse devices
	m_pDIObject->CreateDevice(GUID_SysKeyboard, &m_pDIKeyboard, NULL);
	m_pDIObject->CreateDevice(GUID_SysMouse, &m_pDIMouse, NULL);


	// set the cooperative level
	m_pDIKeyboard->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
	m_pDIMouse->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);

	// set data format
	m_pDIKeyboard->SetDataFormat(&c_dfDIKeyboard);
	m_pDIMouse->SetDataFormat(&c_dfDIMouse);

	// attempt to acquire the devices
	HRESULT hr;

	hr = m_pDIKeyboard->Acquire();
	hr = m_pDIMouse->Acquire();

	m_bInitialized = true;
	return true;			// only return true if devices were acquired successfully
}

// handle input
bool DInput::PollDevices()
{
	if(!m_bInitialized)
		return false;

	HRESULT hr;
	for(int i = 0; i < 256; i++)	// for every potential element of the buffer
	{
		if(keyHeld(i))	// if the key was just pressed
		{
			if(!m_kbWasHit[i])			// check if the key is registered as not being hit
				m_kbWasHit[i] = true;	// if it wasn't just hit, then register it as being hit now
		}
		else			// if the key was not just pressed
		{
			if(m_kbWasHit[i])			// check if the key is registered as being hit
				m_kbWasHit[i] = false;	// if it is still registered as being hit, update and say that it hasn't
		}

	}

	// get the state of the keyboard
	hr = m_pDIKeyboard->GetDeviceState(sizeof(m_kbBuffer), (void*)&m_kbBuffer);
	if(FAILED(hr))
	{	
		ZeroMemory(m_kbBuffer, sizeof(m_kbBuffer));
		hr = m_pDIKeyboard->Acquire();		// attempt to re-acquire the device if unable to GetDeviceState
	}

	for(int i = 0; i < 4; i++)
	{
		if(mouseButtonDown(i))
		{
			if(!m_bMouseButtonDown[i])
				m_bMouseButtonDown[i] = true;
		}
		else
		{
			if(m_bMouseButtonDown[i])
				m_bMouseButtonDown[i] = false;
		}
	}

	// get the state of the mouse
	hr = m_pDIMouse->GetDeviceState(sizeof(m_mouseState), (void*)&m_mouseState);

	if(FAILED(hr))
	{
		ZeroMemory(&m_mouseState, sizeof(m_mouseState));
		hr = m_pDIMouse->Acquire();			// attempt to re-acquire the device if unable to GetDeviceState
	}

	// get the coordinates of the cursor
	GetCursorPos(&m_CursorPos);
	ScreenToClient(m_hWnd, &m_CursorPos);

	return true;

}


bool DInput::keyPressed(unsigned char key)
{
	if((m_kbBuffer[key] & 0x80) && !m_kbWasHit[key])
		return true;

	return false;
}
bool DInput::keyHeld(unsigned char key)
{
	if(m_kbBuffer[key] & 0x80)
		return true;

	return false;
}

bool DInput::mouseButtonDown(int button)
{
	return (m_mouseState.rgbButtons[button] & 0x80) != 0;
}

bool DInput::mouseButtonHit(int button)
{
	if((m_mouseState.rgbButtons[button] & 0x80) && !m_bMouseButtonDown[button])
		return true;

	return false;
}
bool DInput::mouseButtonUp(int button)
{
	if((m_mouseState.rgbButtons[button] & 0x80) == 0 && m_bMouseButtonDown[button])
		return true;

	return false;
}
float DInput::mouseDX()
{
	return (float)m_mouseState.lX;
}

float DInput::mouseDY()
{
	return (float)m_mouseState.lY;
}
float DInput::mouseDZ()
{
	return (float)m_mouseState.lZ;
}

void DInput::Release()
{
	if(m_pDIKeyboard)
	{
		m_pDIKeyboard->Unacquire();
		m_pDIKeyboard->Release();
		m_pDIKeyboard = NULL;
	}

	if(m_pDIMouse)
	{
		m_pDIMouse->Unacquire();
		m_pDIMouse->Release();
		m_pDIMouse = NULL;
	}

	if(m_pDIObject)
	{
		m_pDIObject->Release();
		m_pDIObject = NULL;
	}
}

// release memory
DInput::~DInput()
{
	Release();
}